/*!
    \file      change log.txt
    \brief   change log for GD32W51x firmware

    \version 2026-04-15, V2.0.0, firmware for gd32w51x_f5hc
*/

/*
    Copyright (c) 2026, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/
******************* V2.0.0 2026-03-20 ******************************************************************************************
______________________Common______________________________________________________________________________________________
Version updated to add GD32F5HC series
______________________________________________________________________________________________________________________
******************* V1.3.0 2024-07-26 ******************************************************************************************
______________________Common______________________________________________________________________________________________
Fix file:
gd32w51x_it.c
fix reason:
The FPU is enabled for interrupts by default, so an interrupt service function needs to be added.
V1.2.0:
none
V1.3.0:
/*!
    \brief      this function handles FPU exception
    \param[in]  none
    \param[out] none
    \retval     none
*/
void FPU_IRQHandler(void)
{
    /* if FPU exception occurs, go to infinite loop */
    while(1) {
    }
}

Fix file:
gd32w51x_it.h
fix reason:
Add the declaration of the FPU_IRQHandler function. 
V1.2.0:
none
V1.3.0:
/* this function handles FPU exception */
void FPU_IRQHandler(void);

Fix file:
All functions in the file that involve the use of a serial port.
fix reason:
Modify the serial port redirection function to adapt to the Embedded Builder IDE.
V1.2.0:
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM0, (uint8_t)ch);
    while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));
    return ch;
}
V1.3.0:
#ifdef GD_ECLIPSE_GCC
/* retarget the C library printf function to the USART, in Eclipse GCC environment */
int __io_putchar(int ch)
{
    usart_data_transmit(EVAL_COM0, (uint8_t) ch );
    while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));
    return ch;
}
#else
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM0, (uint8_t)ch);
    while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));

    return ch;
}
#endif /* GD_ECLIPSE_GCC */

Fix file:
../Firmware/CMSIS/GD/GD32W51x/Include/gd32w51x.h
fix reason:
Add a firmware library version acquisition function to the firmware library. 
V1.2.0:
/* GD32W51x firmware library version number V1.0 */
#define __GD32W51x_STDPERIPH_VERSION_MAIN   (0x03) /*!< [31:24] main version */
#define __GD32W51x_STDPERIPH_VERSION_SUB1   (0x00) /*!< [23:16] sub1 version */
#define __GD32W51x_STDPERIPH_VERSION_SUB2   (0x00) /*!< [15:8]  sub2 version */
#define __GD32W51x_STDPERIPH_VERSION_RC     (0x00) /*!< [7:0]  release candidate */ 
#define __GD32W51x_STDPERIPH_VERSION        ((__GD32W51x_STDPERIPH_VERSION_MAIN << 24)\
                                            |(__GD32W51x_STDPERIPH_VERSION_SUB1 << 16)\
                                            |(__GD32W51x_STDPERIPH_VERSION_SUB2 << 8)\
                                            |(__GD32W51x_STDPERIPH_VERSION_RC))
V1.3.0:
/* GD32W51x firmware library version number */
#define __GD32W51X_STDPERIPH_VERSION_MAIN   (0x01) /*!< [31:24] main version */
#define __GD32W51X_STDPERIPH_VERSION_SUB1   (0x03) /*!< [23:16] sub1 version */
#define __GD32W51X_STDPERIPH_VERSION_SUB2   (0x00) /*!< [15:8]  sub2 version */
#define __GD32W51X_STDPERIPH_VERSION_RC     (0x00) /*!< [7:0]  release candidate */ 
#define __GD32W51X_STDPERIPH_VERSION        ((__GD32W51X_STDPERIPH_VERSION_MAIN << 24)\
                                            |(__GD32W51X_STDPERIPH_VERSION_SUB1 << 16)\
                                            |(__GD32W51X_STDPERIPH_VERSION_SUB2 << 8)\
                                            |(__GD32W51X_STDPERIPH_VERSION_RC))

Fix file:
../Firmware/CMSIS/GD/GD32W51x/Include/system_gd32w51x.h
fix reason:
Add a firmware library version acquisition function to the firmware library. 
V1.2.0:
none
V1.3.0:
/* firmware version can be aquired by uncommenting the macro */
#define __FIRMWARE_VERSION_DEFINE
#ifdef __FIRMWARE_VERSION_DEFINE
/* get firmware version */
extern uint32_t gd32w51x_firmware_version_get(void);
#endif /* __FIRMWARE_VERSION_DEFINE */

Fix file:
../Firmware/CMSIS/GD/GD32W51x/Source/gd32w51x.c
fix reason:
Add a firmware library version acquisition function to the firmware library. 
V1.2.0:
none
V1.3.0:
#ifdef __FIRMWARE_VERSION_DEFINE
/*!
    \brief      get firmware version
    \param[in]  none
    \param[out] none
    \retval     firmware version
*/
uint32_t gd32w51x_firmware_version_get(void)
{
    return __GD32W51X_STDPERIPH_VERSION;
}
#endif /* __FIRMWARE_VERSION_DEFINE */

Fix file:
../Firmware/CMSIS/GD/GD32W51x/Source/system_gd32w51x.c
fix reason: 
The reset value of RCU_CFG0 is 0x00009400. Directly setting or clearing in the function that configures different clock frequencies may result 
in the configuration not taking effect. Now, clear it first and then configure it.
V1.2.0:
none
V1.3.0:
/* reset the RCU_CFG0 AHBPSC bits */
RCU_CFG0 &= ~ RCU_CFG0_AHBPSC;
/* reset the RCU_CFG0 APB1PSC bits */
RCU_CFG0 &= ~ RCU_CFG0_APB1PSC;
/* reset the RCU_CFG0 APB2PSC bits */
RCU_CFG0 &= ~ RCU_CFG0_APB2PSC;
__________________________________________________________________________________________________________________________

________________________Module TIMER _______________________________________________________________________________________
Fix file:
../Examples/TIMER/TIMERs_cascadesynchro/main.c
../Examples/TIMER/TIMERs_parallelsynchro/main.c
./Examples/TIMER/TIMERs_parallelsynchro/readme.txt
fix reason: 
Change "ITR" in the comment to "ITI".
V1.2.0:
- The ITR1(TIMER1) is used as input trigger
- The ITR2(TIMER2) is used as input trigger
V1.3.0:
- The ITI1(TIMER1) is used as input trigger
- The ITI2(TIMER2) is used as input trigger
__________________________________________________________________________________________________________________________

______________________Module CAU_____________________________________________________________________________________________
Fix file:
../Firmware/GD32H7xx_standard_peripheral/Include/gd32h7xx_cau.h
../Firmware/GD32H7xx_standard_peripheral/Source/gd32h7xx_cau.c
fix reason: 
The cau_flag_get function cannot correctly obtain the flag, which poses a risk.
V1.2.0:
/* cau_stat1 register value */
#define CAU_FLAG_INFIFO             CAU_STAT1_ISTA                             /*!< IN FIFO flag status */
#define CAU_FLAG_OUTFIFO            CAU_STAT1_OSTA                             /*!< OUT FIFO flag status */

FlagStatus cau_flag_get(uint32_t flag)
{
    uint32_t reg = 0U;
    FlagStatus ret_flag = RESET;

    /* check if the flag is in CAU_STAT1 register */
    if(RESET != (flag & FLAG_MASK)){ 
        reg = CAU_STAT1;
    }else{
        /* the flag is in CAU_STAT0 register */
        reg = CAU_STAT0;
    }

    /* check the status of the specified CAU flag */
    if(RESET != (reg & flag)){
        ret_flag = SET;
    }
     
    return ret_flag;
}
V1.3.0:
/* cau_stat1 register value */
#define CAU_FLAG_INFIFO             (CAU_STAT1_ISTA | BIT(31))                 /*!< IN FIFO flag status */
#define CAU_FLAG_OUTFIFO            (CAU_STAT1_OSTA | BIT(31))                 /*!< OUT FIFO flag status */

FlagStatus cau_flag_get(uint32_t flag)
{
    uint32_t reg = 0U;
    FlagStatus ret_flag = RESET;

    /* check if the flag is in CAU_STAT1 register */
    if(1U == (flag >> 31U)){ 
        reg = CAU_STAT1;
    }else{
        /* the flag is in CAU_STAT0 register */
        reg = CAU_STAT0;
    }

    /* check the status of the specified CAU flag */
    if(0U != (reg & flag)){
        ret_flag = SET;
    }
     
    return ret_flag;
}

Fix file:
../Example/CAU/CAU_AES_GCM_CCM_CFB_OFB_mode/main.c
../Example/CAU/CAU_AES_modes/main.c
../Example/CAU/CAU_AESECB_mode/main.c
../Example/CAU/CAU_DES_TDES_modes/main.c
../Example/CAU/CAU_TDESECB_mode/main.c
../Example/CAU/CAU_AES_GCM_CCM_CFB_OFB_mode/Expected_Results.txt
../Example/CAU/CAU_AES_modes/Expected_Results.txt
../Example/CAU/CAU_AESECB_mode/Expected_Results.txt
../Example/CAU/CAU_DES_TDES_modes/Expected_Results.txt
../Example/CAU/CAU_TDESECB_mode/Expected_Results.txt
fix reason: 
Optimize function interfaces and update the content of arrays.
V1.2.0:
plain text:
0x6B 0xC1 0xBE 0xE2 0x2E 0x40 0x9F 0x96 0xE9 0x3D 0x7E 0x11 0x73 0x93 0x17 0x2A   [Block 0] 
0xAE 0x2D 0x8A 0x57 0x1E 0x03 0xAC 0x9C 0x9E 0xB7 0x6F 0xAC 0x45 0xAF 0x8E 0x51   [Block 1] 
0x30 0xC8 0x1C 0x46 0xA3 0x5C 0xE4 0x11 0xE5 0xFB 0xC1 0x19 0x1A 0x0A 0x52 0xEF   [Block 2] 
0xF6 0x9F 0x24 0x45 0xDF 0x4F 0x9B 0x17 0xAD 0x2B 0x41 0x7B 0xE6 0x6C 0x37 0x10   [Block 3] 

encryption in GCM mode
encrypted data:
0x3B 0x3F 0xD9 0x2E 0xB7 0x2D 0xAD 0x20 0x33 0x34 0x49 0xF8 0xE8 0x3C 0xFB 0x4A   [Block 0] 
0x01 0x0C 0x04 0x19 0x99 0xE0 0x3F 0x36 0x44 0x86 0x24 0x48 0x3E 0x58 0x2D 0x0E   [Block 1] 
0xA6 0x22 0x93 0xCF 0xA6 0xDF 0x74 0x53 0x5C 0x35 0x41 0x81 0x16 0x87 0x74 0xDF   [Block 2] 
0x2D 0x55 0xA5 0x47 0x06 0x27 0x3C 0x50 0xD7 0xB4 0xF8 0xA8 0xCD 0xDC 0x6E 0xD7   [Block 3] 
tag:
0x99 0x75 0x01 0xFA 0x29 0xEB 0xE5 0x54 0x49 0x5F 0xBE 0x0B 0xBA 0xF1 0xD8 0x22   [Block 0] 

encryption in CCM mode
encrypted data:
0x99 0x41 0x6C 0x21 0x5B 0x8F 0xE6 0xD3 0xC9 0x0E 0x23 0xA8 0x58 0x83 0x60 0x38   [Block 0] 
0xCD 0xD2 0xBA 0xCF 0x0A 0xFB 0x2C 0xB0 0xC1 0x0C 0x16 0x29 0xD9 0x3E 0xD7 0x36   [Block 1] 
0x70 0xA8 0xF6 0xD5 0x1F 0xCC 0x2F 0x2D 0x77 0xCA 0x86 0xEA 0x3B 0x25 0x91 0x6C   [Block 2] 
0xEC 0x2C 0xEB 0xDE 0x42 0x55 0x40 0xA9 0xF3 0xB5 0x5F 0xF7 0x90 0x74 0xEE 0x14   [Block 3] 
tag:
0xC3 0x2D 0x8D 0x3B 0x84 0x90 

encryption in CFB mode
encrypted data:
0x3B 0x3F 0xD9 0x2E 0xB7 0x2D 0xAD 0x20 0x33 0x34 0x49 0xF8 0xE8 0x3C 0xFB 0x4A   [Block 0] 
0xC8 0xA6 0x45 0x37 0xA0 0xB3 0xA9 0x3F 0xCD 0xE3 0xCD 0xAD 0x9F 0x1C 0xE5 0x8B   [Block 1] 
0x26 0x75 0x1F 0x67 0xA3 0xCB 0xB1 0x40 0xB1 0x80 0x8C 0xF1 0x87 0xA4 0xF4 0xDF   [Block 2] 
0xC0 0x4B 0x05 0x35 0x7C 0x5D 0x1C 0x0E 0xEA 0xC4 0xC6 0x6F 0x9F 0xF7 0xF2 0xE6   [Block 3] 

encryption in OFB mode
encrypted data:
0x3B 0x3F 0xD9 0x2E 0xB7 0x2D 0xAD 0x20 0x33 0x34 0x49 0xF8 0xE8 0x3C 0xFB 0x4A   [Block 0] 
0x77 0x89 0x50 0x8D 0x16 0x91 0x8F 0x03 0xF5 0x3C 0x52 0xDA 0xC5 0x4E 0xD8 0x25   [Block 1] 
0x97 0x40 0x05 0x1E 0x9C 0x5F 0xEC 0xF6 0x43 0x44 0xF7 0xA8 0x22 0x60 0xED 0xCC   [Block 2] 
0x30 0x4C 0x65 0x28 0xF6 0x59 0xC7 0x78 0x66 0xA5 0x10 0xD9 0xC1 0xD6 0xAE 0x5E   [Block 3] 

decryption in GCM mode
decrypted data:
0x6B 0xC1 0xBE 0xE2 0x2E 0x40 0x9F 0x96 0xE9 0x3D 0x7E 0x11 0x73 0x93 0x17 0x2A   [Block 0] 
0xAE 0x2D 0x8A 0x57 0x1E 0x03 0xAC 0x9C 0x9E 0xB7 0x6F 0xAC 0x45 0xAF 0x8E 0x51   [Block 1] 
0x30 0xC8 0x1C 0x46 0xA3 0x5C 0xE4 0x11 0xE5 0xFB 0xC1 0x19 0x1A 0x0A 0x52 0xEF   [Block 2] 
0xF6 0x9F 0x24 0x45 0xDF 0x4F 0x9B 0x17 0xAD 0x2B 0x41 0x7B 0xE6 0x6C 0x37 0x10   [Block 3] 
tag:
0x99 0x75 0x01 0xFA 0x29 0xEB 0xE5 0x54 0x49 0x5F 0xBE 0x0B 0xBA 0xF1 0xD8 0x22   [Block 0] 

decryption in CCM mode
decrypted data:
0x6B 0xC1 0xBE 0xE2 0x2E 0x40 0x9F 0x96 0xE9 0x3D 0x7E 0x11 0x73 0x93 0x17 0x2A   [Block 0] 
0xAE 0x2D 0x8A 0x57 0x1E 0x03 0xAC 0x9C 0x9E 0xB7 0x6F 0xAC 0x45 0xAF 0x8E 0x51   [Block 1] 
0x30 0xC8 0x1C 0x46 0xA3 0x5C 0xE4 0x11 0xE5 0xFB 0xC1 0x19 0x1A 0x0A 0x52 0xEF   [Block 2] 
0xF6 0x9F 0x24 0x45 0xDF 0x4F 0x9B 0x17 0xAD 0x2B 0x41 0x7B 0xE6 0x6C 0x37 0x10   [Block 3] 
tag:
0xC3 0x2D 0x8D 0x3B 0x84 0x90 

decryption in CFB mode
decrypted data:
0x6B 0xC1 0xBE 0xE2 0x2E 0x40 0x9F 0x96 0xE9 0x3D 0x7E 0x11 0x73 0x93 0x17 0x2A   [Block 0] 
0xAE 0x2D 0x8A 0x57 0x1E 0x03 0xAC 0x9C 0x9E 0xB7 0x6F 0xAC 0x45 0xAF 0x8E 0x51   [Block 1] 
0x30 0xC8 0x1C 0x46 0xA3 0x5C 0xE4 0x11 0xE5 0xFB 0xC1 0x19 0x1A 0x0A 0x52 0xEF   [Block 2] 
0xF6 0x9F 0x24 0x45 0xDF 0x4F 0x9B 0x17 0xAD 0x2B 0x41 0x7B 0xE6 0x6C 0x37 0x10   [Block 3] 

decryption in OFB mode
decrypted data:
0x6B 0xC1 0xBE 0xE2 0x2E 0x40 0x9F 0x96 0xE9 0x3D 0x7E 0x11 0x73 0x93 0x17 0x2A   [Block 0] 
0xAE 0x2D 0x8A 0x57 0x1E 0x03 0xAC 0x9C 0x9E 0xB7 0x6F 0xAC 0x45 0xAF 0x8E 0x51   [Block 1] 
0x30 0xC8 0x1C 0x46 0xA3 0x5C 0xE4 0x11 0xE5 0xFB 0xC1 0x19 0x1A 0x0A 0x52 0xEF   [Block 2] 
0xF6 0x9F 0x24 0x45 0xDF 0x4F 0x9B 0x17 0xAD 0x2B 0x41 0x7B 0xE6 0x6C 0x37 0x10   [Block 3]
V1.3.0:
plain text:
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
0x38 0x39 0x41 0x42 0x43 0x44 0x45 0x46 
0x47 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 
0x4F 0x50 0x51 0x52 0x53 0x54 0x55 0x56 
0x57 0x58 0x59 0x5A 0x61 0x62 0x63 0x64 
0x65 0x66 0x67 0x68 0x69 0x6A 0x6B 0x6C 
0x6D 0x6E 0x6F 0x70 0x71 0x72 0x73 0x74 
0x75 0x76 0x77 0x78 0x79 0x7A 0x7A 0x7A 

encryption in GCM mode
encrypted data:
0xA5 0x6E 0xC1 0x3E 0xDA 0x96 0xD5 0xB7 
0x11 0xC4 0x07 0x18 0x67 0xCC 0xCE 0x51 
0x13 0x4D 0x93 0x18 0xB2 0xA7 0x07 0x8D 
0x5C 0x63 0x19 0xD5 0x17 0x51 0x1F 0xCD 
0xD9 0x4C 0x31 0x42 0x16 0x53 0x0F 0x37 
0x3A 0x04 0x9D 0x95 0x51 0x0C 0x9E 0x06 
0xF5 0xCF 0x4A 0x2E 0xA2 0x8F 0x97 0xA4 
0x05 0x64 0xBB 0xEA 0x50 0x0A 0x16 0x3E 
tag:
0xBB 0x62 0x9E 0x21 0xF3 0x0D 0xF5 0x06 
0x05 0x0E 0x0B 0xD2 0x98 0x42 0xF2 0xFC 

encryption in CCM mode
encrypted data:
0x97 0x8E 0x3C 0x60 0x10 0xC9 0x0D 0x3D 
0xE9 0x4C 0x9C 0x8E 0x5D 0x40 0x69 0x5F 
0xC2 0x30 0xFD 0x0A 0x42 0xF1 0xC5 0x02 
0x2C 0x98 0xAC 0x1C 0x45 0x33 0x1A 0x78 
0x84 0x83 0xF1 0xEB 0xDD 0xD3 0x06 0xA2 
0xF6 0x5D 0xE5 0x79 0xB9 0xC6 0x63 0x01 
0xB8 0x70 0x74 0xCA 0xCE 0xA3 0x17 0xA0 
0x97 0xE9 0x7E 0xA8 0x80 0xEF 0x0D 0x77 
tag:
0xC4 0x04 0x53 0xD9 0xC5 0xE7 
encryption in CFB mode
encrypted data:
0xA5 0x6E 0xC1 0x3E 0xDA 0x96 0xD5 0xB7 
0x11 0xC4 0x07 0x18 0x67 0xCC 0xCE 0x51 
0x1E 0xD7 0x36 0x6B 0x50 0x24 0xE9 0xF3 
0x3F 0xF9 0xE9 0x66 0xF7 0xBD 0xF3 0x0D 
0xB4 0x0E 0xF5 0x31 0x93 0x80 0x40 0x11 
0x62 0xF0 0x17 0x85 0xD5 0x17 0xAA 0x6A 
0xA1 0x01 0xFE 0xEE 0x53 0xEF 0x1A 0x04 
0xC4 0x71 0x8C 0x44 0x91 0xC5 0x62 0x4F 

encryption in OFB mode
encrypted data:
0xA5 0x6E 0xC1 0x3E 0xDA 0x96 0xD5 0xB7 
0x11 0xC4 0x07 0x18 0x67 0xCC 0xCE 0x51 
0x76 0x92 0x8F 0xC9 0x8E 0xE3 0x92 0x0F 
0x0D 0x2A 0xCB 0x3B 0xE8 0xCC 0x69 0x25 
0x53 0x96 0x3A 0x4F 0x3F 0xB1 0xF7 0x0E 
0x88 0xD0 0xBC 0xE7 0x11 0xF9 0x1E 0x5F 
0x66 0x36 0xCF 0xE0 0x89 0x4F 0xE7 0xA7 
0xC8 0x66 0x23 0x66 0x34 0x39 0xD4 0x29 

decryption in GCM mode
decrypted data:
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
0x38 0x39 0x41 0x42 0x43 0x44 0x45 0x46 
0x47 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 
0x4F 0x50 0x51 0x52 0x53 0x54 0x55 0x56 
0x57 0x58 0x59 0x5A 0x61 0x62 0x63 0x64 
0x65 0x66 0x67 0x68 0x69 0x6A 0x6B 0x6C 
0x6D 0x6E 0x6F 0x70 0x71 0x72 0x73 0x74 
0x75 0x76 0x77 0x78 0x79 0x7A 0x7A 0x7A 
tag:
0xBB 0x62 0x9E 0x21 0xF3 0x0D 0xF5 0x06 
0x05 0x0E 0x0B 0xD2 0x98 0x42 0xF2 0xFC 

decryption in CCM mode
decrypted data:
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
0x38 0x39 0x41 0x42 0x43 0x44 0x45 0x46 
0x47 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 
0x4F 0x50 0x51 0x52 0x53 0x54 0x55 0x56 
0x57 0x58 0x59 0x5A 0x61 0x62 0x63 0x64 
0x65 0x66 0x67 0x68 0x69 0x6A 0x6B 0x6C 
0x6D 0x6E 0x6F 0x70 0x71 0x72 0x73 0x74 
0x75 0x76 0x77 0x78 0x79 0x7A 0x7A 0x7A 
tag:
0xC4 0x04 0x53 0xD9 0xC5 0xE7 

decryption in CFB mode
decrypted data:
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
0x38 0x39 0x41 0x42 0x43 0x44 0x45 0x46 
0x47 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 
0x4F 0x50 0x51 0x52 0x53 0x54 0x55 0x56 
0x57 0x58 0x59 0x5A 0x61 0x62 0x63 0x64 
0x65 0x66 0x67 0x68 0x69 0x6A 0x6B 0x6C 
0x6D 0x6E 0x6F 0x70 0x71 0x72 0x73 0x74 
0x75 0x76 0x77 0x78 0x79 0x7A 0x7A 0x7A 

decryption in OFB mode
decrypted data:
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
0x38 0x39 0x41 0x42 0x43 0x44 0x45 0x46 
0x47 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 
0x4F 0x50 0x51 0x52 0x53 0x54 0x55 0x56 
0x57 0x58 0x59 0x5A 0x61 0x62 0x63 0x64 
0x65 0x66 0x67 0x68 0x69 0x6A 0x6B 0x6C 
0x6D 0x6E 0x6F 0x70 0x71 0x72 0x73 0x74 
0x75 0x76 0x77 0x78 0x79 0x7A 0x7A 0x7A 

__________________________________________________________________________________________________________________________

______________________Module USBFS_________________________________________________________________________________________________
Fix file:
../Firmware/GD32W51x_usbfs_library/device/class/dfu/Source/dfu_core.c
fix reason: 
Change the USB data interface to a control interface.
V1.2.0
static uint8_t dfu_data_in (usb_dev *udev, uint8_t ep_num);

static uint8_t dfu_data_in (usb_dev *udev, uint8_t ep_num)
{
    if(0U == ep_num ){
         dfu_getstatus_complete(udev);
    }
     return USBD_OK;
}
V1.3.0
static uint8_t dfu_ctlx_in (usb_dev *udev);

static uint8_t dfu_ctlx_in(usb_dev *udev)
{
    if(0U == ep_num ){
         dfu_getstatus_complete(udev);
    }
     return USBD_OK;
}

Fix file:
../Firmware/GD32W51x_usbfs_library/device/class/iap/Include/usb_iap_core.h
../Firmware/GD32W51x_usbfs_library/device/class/iap/Source/usb_iap_core.c
fix reason: 
Add IAP instructions, check, and option byte write.
V1.2.0
none
V1.3.0:
#define IAP_UPLOAD                          0x07U                                  /*!< upload request */
#define IAP_CHECK_RDP                       0x08U                                  /*!< check rdp state request */

Fix file:
\Firmware\GD32W51x_usbfs_library\device\class\iap\Source\usb_iap_core.c
fix reason: 
Changing IAP download request function due to IAP protocol modification
V1.2.0
/*!
    \brief      handle the IAP_DNLOAD request
    \param[in]  udev: pointer to usb device instance
    \param[out] none
    \retval     none
*/
static void iap_req_dnload(usb_dev *udev)
{
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    if (0U != iap->transfer_times) {
        if (1U == iap->transfer_times) {
            if (0U == iap->lps) {
                iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE);
            } else {
                iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE);
                iap->lps = 0U;
            }

            iap->dev_status[0] = 0x02U;
            iap->dev_status[1] = 0x02U;
            iap_report_send (udev, iap->dev_status, IAP_IN_PACKET);
        } else {
            iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE);

            iap->base_address += TRANSFER_SIZE;
        }

        iap->transfer_times--;
    }
}
V1.3.0:
/*!
    \brief      handle the IAP_DOWNLOAD request
    \param[in]  udev: pointer to USB device instance
    \param[out] none
    \retval     none
*/
static void iap_req_download(usb_dev *udev)
{
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    iap->dev_status[0] = IAP_DEVICE_ID;

    /* get the target address to download */
    iap->base_address  = iap->report_buf[2];
    iap->base_address |= (uint32_t)iap->report_buf[3] << 8;
    iap->base_address |= (uint32_t)iap->report_buf[4] << 16;
    iap->base_address |= (uint32_t)iap->report_buf[5] << 24;

    /* program the target address */
    if(FMC_READY == iap_data_write(&iap->report_buf[6], iap->base_address, TRANSFER_SIZE)) {
        iap->dev_status[1] = OPERATION_SUCCESS;
    } else {
        iap->dev_status[1] = OPERATION_FAIL;
    }

    iap_report_send(udev, iap->dev_status, IAP_IN_PACKET);
}

Fix file:
..\Firmware\GD32W51x_usbfs_library\device\class\iap\Source\usb_iap_core.c
fix reason: 
Optimize the option byte write function for HID IAP.
V1.2.0
none
V1.3.0:
/*!
    \brief      handle the IAP_WRITE_OPTION_BYTE request
    \param[in]  udev: pointer to USB device instance
    \param[out] none
    \retval     none
*/
static void iap_req_write_optionbyte(usb_dev *udev)
{
    uint32_t option_byte_addr = 0U;
    uint16_t option_byte_size = 0U;
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    /* get option byte address address */
    option_byte_addr  = iap->report_buf[2];
    option_byte_addr |= (uint32_t)iap->report_buf[3] << 8;
    option_byte_addr |= (uint32_t)iap->report_buf[4] << 16;
    option_byte_addr |= (uint32_t)iap->report_buf[5] << 24;

    /* get option byte address size */
    if(OPT_BYTE_ADDR == option_byte_addr) {
        option_byte_size = OPT_BYTE_SIZE;
    }

    iap->dev_status[0] = IAP_DEVICE_ID;

    /* write option byte address data */
    if(FMC_READY == option_byte_write(option_byte_addr, &iap->report_buf[6], option_byte_size)) {
        iap->dev_status[1] = OB_WRITE_SUCCESS;
    } else {
        iap->dev_status[1] = OPERATION_FAIL;
    }

    iap_report_send(udev, iap->dev_status, IAP_IN_PACKET);
}

Fix file:
..\Firmware\GD32W51x_usbfs_library\device\class\iap\Source\usb_iap_core.c
fix reason: 
Changing IAP erase flash request function due to IAP protocol modification
V1.2.0
/*!
    \brief      handle the IAP_ERASE request
    \param[in]  udev: pointer to usb device instance
    \param[out] none
    \retval     none
*/
static void iap_req_erase(usb_dev *udev)
{
    uint32_t addr = 0U;

    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    /* get base address to erase */
    iap->base_address  = iap->report_buf[2];
    iap->base_address |= iap->report_buf[3] << 8U;
    iap->base_address |= iap->report_buf[4] << 16U;
    iap->base_address |= iap->report_buf[5] << 24U;

    /* get file length */
    iap->file_length = iap->report_buf[7];
    iap->file_length |= iap->report_buf[8] << 8U;
    iap->file_length |= iap->report_buf[9] << 16U;
    iap->file_length |= iap->report_buf[10] << 24U;

    iap->lps = iap->file_length % TRANSFER_SIZE;
    if (0U == iap->lps) {
        iap->transfer_times = iap->file_length / TRANSFER_SIZE;
    } else {
        iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U;
    }

    /* check if the address is in protected area */
    if (IS_PROTECTED_AREA(iap->base_address)) {
        return;
    }

    addr = iap->base_address;

    /* unlock the flash program erase controller */
    fmc_unlock();

    flash_erase(addr, iap->file_length, iap->report_buf);

    fmc_lock();

    iap->dev_status[0] = 0x02U;
    iap->dev_status[1] = 0x01U;

    usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET);
}
V1.3.0:
/*!
    \brief      handle the IAP_ERASE request
    \param[in]  udev: pointer to USB device instance
    \param[out] none
    \retval     none
*/
static void iap_req_erase(usb_dev *udev)
{
    uint32_t addr = 0U;
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    /* get base address to erase */
    iap->base_address  = iap->report_buf[2];
    iap->base_address |= (uint32_t)iap->report_buf[3] << 8;
    iap->base_address |= (uint32_t)iap->report_buf[4] << 16;
    iap->base_address |= (uint32_t)iap->report_buf[5] << 24;

    /* get file length */
    iap->file_length = iap->report_buf[6];
    iap->file_length |= (uint32_t)iap->report_buf[7] << 8;
    iap->file_length |= (uint32_t)iap->report_buf[8] << 16;
    iap->file_length |= (uint32_t)iap->report_buf[9] << 24;

    /* check if the address is in protected area */
    if(IS_PROTECTED_AREA(iap->base_address)) {
        return;
    }

    addr = iap->base_address;
    iap->dev_status[0] = IAP_DEVICE_ID;

    if(FMC_READY == flash_erase(addr, iap->file_length)) {
        iap->dev_status[1] = OPERATION_SUCCESS;
    } else {
        iap->dev_status[1] = OPERATION_FAIL;
    }

    usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET);
}

Fix file:
..\Firmware\GD32W51x_usbfs_library\device\class\iap\Source\usb_iap_core.c
fix reason: 
Changing IAP read option byte request function due to IAP protocol modification
V1.2.0
/*!
    \brief      handle the IAP_OPTION_BYTE request
    \param[in]  udev: pointer to USB device instance
    \param[in]  option_num: number of option byte
    \param[out] none
    \retval     none
*/
static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num)
{
    uint8_t i = 0U;
    uint32_t address = 0U;

    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    iap->option_byte[0] = 0x02U;

    if (0x01U == option_num) {
        address = OPT_BYTE_ADDR1;
#ifdef OPT_BYTE_ADDR2
    } else if (0x02U == option_num) {
        address = OPT_BYTE_ADDR2;
#endif
    } else {
        return;
    }

    for (i = 1U; i < 17U; i++) {
        iap->option_byte[i] = *(uint8_t *)address;
        address++;
    }

    iap_report_send (udev, iap->option_byte, IAP_IN_PACKET);
}
V1.3.0:
/*!
    \brief      handle the IAP_READ_OPTION_BYTE request
    \param[in]  udev: pointer to USB device instance
    \param[out] none
    \retval     none
*/
static void iap_req_read_optionbyte(usb_dev *udev)
{
    uint8_t i = 0U;
    uint32_t option_size = 0U, temp = 0U, option_address = 0U;
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    /* read option address address */
    option_address = iap->report_buf[2] + (iap->report_buf[3] << 8) + (iap->report_buf[4] << 16) + (iap->report_buf[5] << 24);

    iap->option_byte[0] = IAP_DEVICE_ID;

    if(OPT_BYTE_ADDR == option_address) {
        option_size = OPT_BYTE_SIZE;
    }

    /* read option address content */
    for(i = 0U; i < (option_size / 4U); i++) {
        temp =  *(uint32_t *)option_address;
        iap->option_byte[4 * i + 5] = temp >> 24;
        iap->option_byte[4 * i + 4] = temp >> 16;
        iap->option_byte[4 * i + 3] = temp >> 8;
        iap->option_byte[4 * i + 2] = temp;
        option_address = option_address + 4U;
    }
    iap->option_byte[1] = OPERATION_SUCCESS;

    iap_report_send(udev, iap->option_byte, IAP_IN_PACKET);
}

Fix file:
..\Firmware\GD32W51x_usbfs_library\device\class\iap\Source\usb_iap_core.c
fix reason: 
Optimize the functionality of the HID IAP
V1.2.0
/*!
    \brief      handle the IAP_LEAVE request
    \param[in]  udev: pointer to usb device instance
    \param[out] none
    \retval     none
*/
static void iap_req_leave(usb_dev *udev)
{
    /* lock the internal flash */
    fmc_lock();

    /* generate system reset to allow jumping to the user code */
    NVIC_SystemReset();
}
V1.3.0:
/*!
    \brief      handle the IAP_LEAVE request
    \param[in]  udev: pointer to USB device instance
    \param[out] none
    \retval     none
*/
static void iap_req_leave(usb_dev *udev)
{
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    /* get base address to jump */
    iap->base_address  = iap->report_buf[2];
    iap->base_address |= (uint32_t)iap->report_buf[3] << 8;
    iap->base_address |= (uint32_t)iap->report_buf[4] << 16;
    iap->base_address |= (uint32_t)iap->report_buf[5] << 24;

    iap->dev_status[0] = IAP_DEVICE_ID;
    iap->dev_status[1] = LEAVE_FINISH;

    usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET);

    usbd_disconnect(udev);

    /* reset register */
    register_reset();

    /* jump to target */
    jump_to_execute(iap->base_address);
}

Fix file:
..\Firmware\GD32W51x_usbfs_library\device\class\iap\Source\usb_iap_core.c
fix reason: 
Optimize the command upload functionality of the HID IAP functions for flash.
V1.2.0
none
V1.3.0:
/*!
    \brief      handle the IAP_UPLOAD request
    \param[in]  udev: pointer to USB device instance
    \param[out] none
    \retval     none
*/
static void iap_req_upload(usb_dev *udev)
{
    uint16_t packet_valid_length = 0U, i= 0U;
    uint32_t bin_flash_addr = APP_LOADED_ADDR;
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    iap->bin_addr[0] = IAP_DEVICE_ID;

    /* get target flash address */
    bin_flash_addr  = iap->report_buf[2];
    bin_flash_addr |= (uint32_t)iap->report_buf[3] << 8;
    bin_flash_addr |= (uint32_t)iap->report_buf[4] << 16;
    bin_flash_addr |= (uint32_t)iap->report_buf[5] << 24;

    /* get current packet valid length */
    packet_valid_length = iap->report_buf[6];
    packet_valid_length |= iap->report_buf[7] << 8;

    /* get target flash address content */
    for(i = 0U; i < packet_valid_length; i++) {
        iap->bin_addr[i + 1] = REG8(bin_flash_addr + i);
    }

    iap_report_send(udev, iap->bin_addr, IAP_IN_PACKET);
}

Fix file:
..\Firmware\GD32W51x_usbfs_library\device\class\iap\Source\usb_iap_core.c
fix reason: 
Optimize the functionality of the HID IAP functions, and add a function to check for read protection.
V1.2.0
none
V1.3.0:
/*!
    \brief      handle the IAP_CHECK_RDP request
    \param[in]  udev: pointer to USB device instance
    \param[out] none
    \retval     none
*/
static void iap_check_rdp(usb_dev *udev)
{
    uint8_t mode = 0U;
    usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE];

    /* check whether the SPC bit of FMC module is normal state */
    if(0xA5U != REG8(OPT_BYTE_ADDR)) {
        mode = IS_RDP_MODE;
    } else {
        mode = IS_NORMAL_MODE;
    }

    iap->bin_addr[0] = IAP_DEVICE_ID;
    iap->bin_addr[1] = mode;

    iap_report_send(udev, iap->bin_addr, IAP_IN_PACKET);
}

Fix file:
../Example/USBFS/usb_device/./usb_conf.h
fix reason: 
Optimize FIFO allocation and cancel the SOF output.
V1.2.0
#ifdef USB_FS_CORE
    #define RX_FIFO_FS_SIZE                         128U
    #define TX0_FIFO_FS_SIZE                        64U
    #define TX1_FIFO_FS_SIZE                        128U
    #define TX2_FIFO_FS_SIZE                        0U
    #define TX3_FIFO_FS_SIZE                        0U
#endif /* USB_FS_CORE */

#define USB_SOF_OUTPUT              1U
V1.3.0:
+/* USB FIFO size config */
#define RX_FIFO_FS_SIZE                         128U
#define TX0_FIFO_FS_SIZE                        64U
#define TX1_FIFO_FS_SIZE                        128U
#define TX2_FIFO_FS_SIZE                        0U
#define TX0_FIFO_FS_SIZE                        32U
#define TX1_FIFO_FS_SIZE                        96U
#define TX2_FIFO_FS_SIZE                        64U
#define TX3_FIFO_FS_SIZE                        0U
#endif /* USB_FS_CORE */
#define USB_SOF_OUTPUT              1U
#define USB_SOF_OUTPUT              0U

Fix file:
..Example/USBFS/usb_device/audio/inc/usbd_conf.h
fix reason: 
Add a microphone interface.
V1.2.0
define USBD_ITF_MAX_NUM                     2U
V1.3.0:
#define USBD_ITF_MAX_NUM                    3U

Fix file:
../Example/USBFS/usb_device/././gd32w51x_hw.c
fix reason: 
Add USB_LOW_POWER control to each USB class.
V1.2.0
    /* enable the power module clock */
    rcu_periph_clock_enable(RCU_PMU);
    /* USB wakeup EXTI line configuration */
    exti_interrupt_flag_clear(EXTI_21);
    exti_init(EXTI_21, EXTI_INTERRUPT, EXTI_TRIG_RISING);
    exti_interrupt_enable(EXTI_21);
    nvic_irq_enable(USBFS_WKUP_IRQn, 1U, 0U);
V1.3.0:
    nvic_irq_enable(USBFS_WKUP_IRQn, 1U, 0U);
#if USB_LOW_POWER
    /* enable the power module clock */
    rcu_periph_clock_enable(RCU_PMU);

    /* USB wakeup EXTI line configuration */
    exti_interrupt_flag_clear(EXTI_21);
    exti_init(EXTI_21, EXTI_INTERRUPT, EXTI_TRIG_RISING);
    exti_interrupt_enable(EXTI_21);
    nvic_irq_enable(USBFS_WKUP_IRQn, 1U, 0U);
#endif /* USB_LOW_POWER */

Fix file:
../Example/USBFS/usb_host/usb_host_msc_udisk/inc/usb_conf.h
../Example/USBFS/usb_host/usb_host_hid_keyboard_mouse/inc/usb_conf.h
fix reason: 
Optimize alignment operations..
V1.2.0
    #define __ALIGN_BEGIN
    #define __ALIGN_END 
V1.3.0:
#if defined (__GNUC__)         /* GNU Compiler */
    #define __ALIGN_END __attribute__ ((aligned (4)))
    #define __ALIGN_BEGIN
#else
    #define __ALIGN_END

    #if defined (__CC_ARM)     /* ARM Compiler */
        #define __ALIGN_BEGIN __align(4)  
    #elif defined (__ICCARM__) /* IAR Compiler */
        #define __ALIGN_BEGIN 
    #elif defined (__TASKING__)/* TASKING Compiler */
        #define __ALIGN_BEGIN __align(4) 
    #endif /* __CC_ARM */  
#endif /* __GNUC__ */

Fix file:
../Example/USBFS/usb_host/usb_host_hid_keyboard_mouse/src/gd32w51x_usb_hw.c
../Example/USBFS/usb_host/usb_host_hid_keyboard_mouse/inc/usb_conf.h
fix reason: 
Optimize alignment operations.
V1.2.0
    #define __ALIGN_BEGIN
    #define __ALIGN_END 
V1.3.0:
#if defined (__GNUC__)         /* GNU Compiler */
    #define __ALIGN_END __attribute__ ((aligned (4)))
    #define __ALIGN_BEGIN
#else
    #define __ALIGN_END

    #if defined (__CC_ARM)     /* ARM Compiler */
        #define __ALIGN_BEGIN __align(4)  
    #elif defined (__ICCARM__) /* IAR Compiler */
        #define __ALIGN_BEGIN 
    #elif defined (__TASKING__)/* TASKING Compiler */
        #define __ALIGN_BEGIN __align(4) 
    #endif /* __CC_ARM */  
#endif /* __GNUC__ */

Fix file:
../Examples/USBFS/usb_device/dev_firmware_update/inc/inter_flash_if.h
fix reason: Optimize the FLASH interface.
V1.2.0
#define OB_RDPT                 0x1ffff800
V1.3.0:
+#define OB_RDPT                 0x40022040

Fix file:
../Examples/USBFS/usb_device/dev_firmware_update/src/inter_flash_if.c
fix reason: Optimize the FLASH interface.
V1.2.0
 static uint8_t flash_if_erase(uint32_t addr)
 {
     fmc_page_erase(addr);
     return MEM_OK;
 }
 
 static uint8_t flash_if_checkaddr(uint32_t addr)
{
   if((addr >= FLASH_START_ADDR) && (addr < FLASH_END_ADDR)) {
        return MEM_OK;
    } else {
        return MEM_FAIL;
    }
}
V1.3.0:
static uint8_t flash_if_erase(uint32_t addr)
{
    /* unlock the internal flash */
    fmc_unlock();

    fmc_page_erase(addr);

    /* lock the internal flash */
    fmc_lock();

    return MEM_OK;
}

static uint8_t flash_if_checkaddr(uint32_t addr)
{
    if((addr >= FLASH_START_ADDR) && (addr < FLASH_END_ADDR)) {
    if ((addr & 0xFBC00000) == FLASH_START_ADDR) {
        return MEM_OK;
    } else if((addr & 0xEFFFFC00) == FMC_BASE) {
          return MEM_OK;
    } else if((addr & 0xEFFFFC00) == EFUSE_BASE) {
          return MEM_OK;
    } else {
        return MEM_FAIL;
    }

}

Fix file:
../Examples/USBFS/usb_device/dev_firmware_update/inc/inter_flash_if.h
fix reason: Optimize the FLASH interface.
V1.2.0
#define OB_RDPT                 0x1ffff800
V1.3.0:
+#define OB_RDPT                 0x40022040

Fix file:
../Examples/USBFS/usb_device/in_application_program_hid/inc/flash_operation.h
fix reason: Optimize the FLASH interface.
V1.2.0
none
V1.3.0:
/* erase flash */
fmc_state_enum flash_erase(uint32_t address, uint32_t file_length);
/* program option byte */
fmc_state_enum option_byte_write(uint32_t opt_addr, uint32_t* data, uint16_t len);
/* write data to sectors of memory */
fmc_state_enum iap_data_write(uint8_t *data, uint32_t addr, uint32_t len);
/* jump to execute application address */
void jump_to_execute(uint32_t addr);
/* reset register */
void register_reset(void);

Fix file:
../Examples/USBFS/usb_device/in_application_program_hid/inc/usbd_conf.h
fix reason: Optimize the FLASH interface.
V1.2.0
#define IAP_IN_PACKET                          24U
#define IAP_OUT_PACKET                         64U
#define PAGE_SIZE                              1024U
#define OPT_BYTE_ADDR1                         0x1FFFF800U
#define OPT_BYTE_ADDR2                         0x1FFEC000U
#define REPORT_IN_COUNT                        0x17U
#define REPORT_OUT_COUNT                       ((TRANSFER_SIZE) + 1U)
V1.3.0:
#define PAGE_SIZE                              4096U
#define OPT_BYTE_ADDR                          0x40022040U
#define OPT_BYTE_SIZE                          32
#define EFUSE_BASE_ADDR                        0x40022800U
#define EFUSE_SIZE                             260
#define REPORT_IN_COUNT                        ((TRANSFER_SIZE) + 5U)
#define REPORT_OUT_COUNT                       ((TRANSFER_SIZE) + 5U)

Fix file:
../Examples/USBFS/usb_device/in_application_program_hid/src/flash_operation.c
fix reason: Optimize the FLASH interface.
V1.2.0
none
V1.3.0:
/*!
    \brief      program option byte
    \param[in]  opt_addr: target address
    \param[in]  data: pointer to target data
    \param[in]  len: length of data to be written (in bytes)
    \param[out] none
    \retval     state of FMC, refer to fmc_state_enum
*/
fmc_state_enum option_byte_write(uint32_t opt_addr, uint32_t* data, uint16_t len)
{
    fmc_state_enum status = FMC_READY;

    /* unlock the flash program erase controller */
    fmc_unlock();

    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR);

    /* authorize the small information block programming */
    ob_unlock();

    FMC_OBR = *data;
    FMC_OBUSER = *(data + 1U);
    FMC_OBWRP0 = *(data + 4U);
    FMC_OBWRP1 = *(data + 7U);

    if(0U == (FMC_OBSTAT & 8U)) {
        FMC_SECMCFG0 = *(data + 2U);
        FMC_DMP0 = *(data + 3U);
        FMC_SECMCFG1 = *(data + 5U);
        FMC_DMP1 = *(data + 6U);
        FMC_SECMCFG2 = *(data + 8U);
        FMC_SECMCFG3 = *(data + 9U);
    }

    ob_start();

    fmc_lock();

    status = fmc_ready_check(FMC_TIMEOUT_COUNT);

    return status;
}

/*!
    \brief      jump to execute address
    \param[in]  addr: execute address
    \param[out] none
    \retval     none
*/
void jump_to_execute(uint32_t addr)
{
    static uint32_t stack_addr, exe_addr;

    /* set interrupt vector base address */
    SCB->VTOR = addr;
    __DSB();

    /* init user application's stack pointer and execute address */
    stack_addr = *(uint32_t *)addr;
    exe_addr = *(uint32_t *)(addr + 4);

    /* re-configure MSP */
    __set_MSP(stack_addr);

    (*((void (*)())exe_addr))();
}

/*!
    \brief      reset all register
    \param[in]  none
    \param[out] none
    \retval     none
*/
void register_reset(void)
{
    /* disable systick */
    SysTick->CTRL = 0U;
    SysTick->VAL = 0U;

    /* reset Peripherals */
    RCU_APB2RST = 0xFFFFFFFF;
    RCU_APB2RST = 0x00000000;
    RCU_APB1RST = 0xFFFFFFFF;
    RCU_APB1RST = 0x00000000;
    RCU_APB2EN = 0x00000000;
    RCU_APB1EN = 0x00000000;

    rcu_deinit();

    RCU_CFG0 = 0x00000000;
    RCU_CFG1 = 0x00000000;

}

/*!
    \brief      check whether FMC is ready or not
    \param[in]  timeout: timeout count
    \param[out] none
    \retval     state of FMC, refer to fmc_state_enum
*/
static fmc_state_enum fmc_ready_check(uint32_t timeout)
{
    fmc_state_enum fmc_state = FMC_BUSY;

    /* wait for FMC ready */
    do {
        /* get FMC state */
        fmc_state = fmc_state_get();
        timeout--;
    } while((FMC_BUSY == fmc_state) && (0x00U != timeout));

    if(FMC_BUSY == fmc_state) {
        fmc_state = FMC_TOERR;
    }

    /* return the FMC state */
    return fmc_state;
}

/*!
    \brief      get the FMC state
    \param[in]  none
    \param[out] none
    \retval     state of FMC, refer to fmc_state_enum
*/
static fmc_state_enum fmc_state_get(void)
{
    fmc_state_enum fmc_state = FMC_READY;

#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
    if((uint32_t)0x00U != (FMC_SECSTAT & (FMC_SECSTAT_SECBUSY))) {
        fmc_state = FMC_BUSY;
    } else {
        if((uint32_t)0x00U != (FMC_SECSTAT & (FMC_SECSTAT_SECERR))) {
            fmc_state = FMC_SECERR;
        } else {
            if((uint32_t)0x00U != (FMC_SECSTAT & (FMC_SECSTAT_SECWPERR))) {
                fmc_state = FMC_WPERR;
            } else {
                if((uint32_t)0x00U != (FMC_STAT & (FMC_STAT_OBERR))) {
                    fmc_state = FMC_OBERR;
                }
            }
        }
    }
#else
    if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_BUSY)) {
        fmc_state = FMC_BUSY;
    } else {
        if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_WPERR)) {
            fmc_state = FMC_WPERR;
        } else {
            if((uint32_t)0x00U != (FMC_STAT & (FMC_STAT_OBERR))) {
                fmc_state = FMC_OBERR;
            }
        }
    }
#endif /* defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3) */

    /* return the FMC state */
    return fmc_state;
}


